<template>
  <el-scrollbar>
    <div class="card-container">
      <div class="card-item" v-for="(item, i) in props.data" :key="i">
        <div class="card-img">
          <to-image style="width: 100%;height: 150px;" :src="image[i]" />
        </div>
        <div class="card-info">
          <div class="card-columns">
            <el-scrollbar max-height="150px">
              <div class="columns_item" v-for="citem in columns" :key="citem.prop">
                <div class="info-label">
                  {{ citem.label }}：
                </div>
                <div class="info-content">
                  <component
                    v-if="citem.component"
                    :is="citem.component"
                    v-bind="componentAttr(item, citem)"
                    v-on="componentEvent(item, citem)"
                  >
                    {{ formatter(item, citem) }}
                  </component>
                  <p :title="item[citem.prop]" v-html="formatter(item, citem)" />
                </div>
              </div>
            </el-scrollbar>
          </div>
          <div class="menu-group" v-if="getMenuList(item).length">
            <p
              v-for="(menu, menuIndex) of getMenuList(item)"
              :key="menuIndex"
              @click="emit('event', menu.event, item, i)"
            >
              {{ menu.name }}
            </p>
            <el-dropdown trigger="click" v-if="getMenuList(item, true).length">
              <p class="el-dropdown-link">
                <span>更多</span>
                <el-icon class="">
                  <DArrowRight />
                </el-icon>
              </p>
              <template #dropdown>
                <el-dropdown-menu
                  v-for="(menu, menuIndex) of getMenuList(item, true)"
                  :key="menuIndex"
                  @click="emit('event', menu.event, item, i)"
                >
                  <el-dropdown-item>{{ menu.name }}</el-dropdown-item>
                </el-dropdown-menu>
              </template>
            </el-dropdown>
          </div>
        </div>
      </div>
    </div>
  </el-scrollbar>
</template>

<script lang="ts" setup>
import { MenuProps, TableColumnsProps } from './types/tableForm'
import { DArrowRight } from '@element-plus/icons'
import { computed } from 'vue'

const props = withDefaults(defineProps<{
  data: any[],
  menus: MenuProps[],
  columns: TableColumnsProps[]
  defaultTableText: string,
  menuMaxNum?: number
}>(), {
  data: () => [],
  menus: () => [],
  columns: () => [],
  defaultTableText: '',
  menuMaxNum: 3
})

interface EmitsType {
  (e: 'event', event: MenuProps['event'], row: any, index: number): void
}
const emit = defineEmits<EmitsType>()

const columns = computed(() => {
  return props.columns.filter(c => !c.img)
})

// 返回图片
const image = computed(() => {
  const list: any[] = []
  props.columns.forEach(c => {
    if (c.img) {
      props.data.forEach(d => {
        list.push(formatter(d, c))
      })
    }
  })
  if (list.length) return list
  return []
})

// 动态组件参数
const componentAttr = (row: any, item: TableColumnsProps) => {
  if (typeof item.attr === 'function') {
    return item.attr(row) || {}
  }
  return item.attr || {}
}
// 动态组件事件
const componentEvent = (row: any, item: TableColumnsProps) => {
  if (typeof item.event === 'function') {
    return item.event(row) || {}
  }
  return item.event || {}
}
// 格式化内容
const formatter = (row: any, item: TableColumnsProps): string => {
  if (item.formatter) {
    return item.formatter(row, item) || props.defaultTableText
  }
  // 异步函数存在，调用
  item.asyncFormat && item.asyncFormat(row, item)
  // 存在img，直接返回prop
  if (item.img) return row[item.prop]
  return row[item.prop] || props.defaultTableText
}

const getMenuList = (row: any, isVisible: boolean = false) => {
  const menus = props.menus.filter((item) => {
    if (typeof item.visible === 'boolean') return !item.visible
    if (typeof item.visible === 'function') return !item.visible(row)
    return true
  })
  let visibleMenus: any = []
  if (menus.length > props.menuMaxNum) {
    visibleMenus = menus.splice(props.menuMaxNum - 1)
  }
  if (isVisible) return visibleMenus
  return menus
}

</script>

<style lang="scss" scoped>
.card-container {
  --card-info-bg-color: #fff;
  --card-header-bg-color: #fff;
  --card-border-color: var(--el-border-color-lighter);
  --card-shadow-color: var(--el-box-shadow-light);
  color: var(--el-text-color-primary);
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  grid-row-gap: 20px;
  grid-column-gap: 20px;
  padding: 10px;
  box-sizing: border-box;
  .card-item {
    width: 100%;
    height: 100%;
    background: var(--card-header-bg-color);
    border-radius: 5px;
    overflow: hidden;
    box-shadow: var(--card-shadow-color);
    .card-info {
      padding-bottom: 0;
      line-height: 1.5em;
      font-size: 14px;
      background: var(--card-info-bg-color);
      .card-columns {
        padding: 10px;
      }
      .columns_item {
        display: flex;
        .info-label {
          width: auto;
          text-align: right;
          color: var(--el-text-color-secondary);
        }
        .info-content {
          color: var(--el-text-color-primary);
          flex: 1;
          overflow: hidden;
          p {
            text-overflow: ellipsis;
            white-space: nowrap;
            overflow: hidden;
          }
        }
      }
    }
    .menu-group {
      display: flex;
      justify-content: center;
      border-top: 1px solid var(--card-border-color);
      >p, .el-dropdown {
        display: flex;
        justify-content: center;
        align-items: center;
        flex: 1;
        text-align: center;
        line-height: inherit;
        color: var(--el-color-primary);
        cursor: pointer;
        margin-right: 10px;
        font-size: 13px;
        &:hover {
          color: var(--el-color-primary-light-2);
        }
        &:active {
          color: var(--el-color-primary);
        }
        &:last-child {
          margin: 0;
        }
      }
      .el-dropdown-link {
        display: flex;
        align-items: center;
      }
      > p {
        padding: $space-margin 0;
        border-right: 1px solid var(--card-border-color);
        &:last-child {
          border: none;
        }
      }
      .el-button {
        width: 100px;
      }
    }
  }
}
</style>
